/*+***********************************************************************************
 Filename: 03_tinycore_step02\src\top.v
 Description: demo the construction of a simple tiny-core.
              step02: ADDI and Jump.

 Modification:
   2022.10.12 Creation   H.Zheng

Copyright (C) 2022  Zheng Hui (hzheng@gzhu.edu.cn)

License: MulanPSL-2.0

***********************************************************************************-*/

module top
(
    input wire [1:0] button,
    input wire sys_clk,
    output wire [5:0] led,
    input wire uart0_rxd,
    output wire uart0_txd
);
    //PLL
    wire clk_200MHz;
    Gowin_rPLL m_pll(
        .clkout(clk_200MHz), //output clkout
        .clkin(sys_clk) //input clkin
    );

    //
    wire reset_n = button[1];

    //core clk
    reg [24:0] counter;

    always @(posedge sys_clk or negedge reset_n) begin
        if (~reset_n) begin
            counter <= 0;
        end
        else begin
            counter <= counter + 1'b1;
        end
    end

    //core
    wire core_clk = counter[24];
    wire [31:0] ibus_addr;
    wire ibus_re;
    wire [31:0] instruction;
    wire [31:0] monitor_port;
    wire ram_ce;
    wire ram_wre;
    wire [8:0] ram_addr;
    wire [31:0] ram_data_in;
    wire [31:0] ram_data_out;
    //
    wire peripheral_ce;
    wire peripheral_wre;
    wire [8:0] peripheral_addr;
    wire [31:0] peripheral_data_in;
    wire [31:0] peripheral_data_out;


    core m_core (
        .core_clk(core_clk),
        .reset_n(reset_n),
        .ibus_addr(ibus_addr),
        .ibus_re(ibus_re),
        .instruction(instruction),
        .ram_ce(ram_ce),
        .ram_wre(ram_wre),
        .ram_addr(ram_addr),
        .ram_data_in(ram_data_in),
        .ram_data_out(ram_data_out),
        //
        .peripheral_ce(peripheral_ce),
        .peripheral_wre(peripheral_wre),
        .peripheral_addr(peripheral_addr),
        .peripheral_data_in(peripheral_data_in),
        .peripheral_data_out(peripheral_data_out),
        //
        .monitor_port(monitor_port)
    );

    //IROM
    //address and control input from core
    //data output to core

    Gowin_pROM I_ROM(
        .dout(instruction), //output [31:0] dout
        .clk(clk_200MHz), //input clk
        .oce(ibus_re), //input oce
        .ce(1'b1), //input ce
        .reset(~reset_n), //input reset
        .ad(ibus_addr[2:0]) //input [2:0] ad
    );

    //display
    wire [5:0] peri_led;

    assign led = {~monitor_port[5:2], peri_led[1:0]};

    //data RAM
    Gowin_SP D_RAM(
        .dout(ram_data_in), //output [31:0] dout
        .clk(clk_200MHz), //input clk
//        .clk(sys_clk), //input clk
        .oce(1'b1), //input oce
        .ce(ram_ce), //input ce
        .reset(~reset_n), //input reset
        .wre(ram_wre), //input wre
        .ad(ram_addr), //input [8:0] ad
        .din(ram_data_out) //input [31:0] din
    );

    //peripherals
    peripheral m_peripheral(
        .clk(sys_clk),
        .reset_n(reset_n),
        .button(button[0]),
//        .led(led),
        .led(peri_led),
        .rxd(uart0_rxd),
        .txd(uart0_txd),
        //
        .ce(peripheral_ce),
        .wre(peripheral_wre),
        .addr(peripheral_addr),
        .data_in(peripheral_data_out),
        .data_out(peripheral_data_in)
    );

endmodule